﻿using restful_sharp.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace restful_sharp
{
    public partial class MainForm : Form
    {
        private BindingList<HeaderItem> requestHeader;
        private BindingList<HeaderItem> responseHeader;
        private HTTP http;

        public MainForm()
        {
            InitializeComponent();

            Init();
        }

        void Init()
        {
            requestHeader = new BindingList<HeaderItem>();
            gridReqHeader.DataSource = requestHeader;
            //gridReqHeader.Columns[0].Width = 60;
            gridReqHeader.Columns[0].Width = 200;
            gridReqHeader.Columns[1].Width = 400;
            gridReqHeader.BackgroundColor = Color.White;

            responseHeader = new BindingList<HeaderItem>();
            gridResHeader.DataSource = responseHeader;
            //gridReqHeader.Columns[0].Width = 60;
            gridResHeader.Columns[0].Width = 200;
            gridResHeader.Columns[1].Width = 400;
            gridResHeader.ReadOnly = true;
            gridResHeader.BackgroundColor = Color.White;

            http = new HTTP();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            var rawBtnText = btnSend.Text;
            btnSend.Enabled = false;
            btnSend.Text = "正在请求...";
            Application.DoEvents();
            ResetResInfo();
            DoSend().ContinueWith(t =>
            {
                Invoke(new MethodInvoker(() =>
                {
                    btnSend.Enabled = true;
                    btnSend.Text = rawBtnText;
                    if (t.IsFaulted)
                    {
                        MessageBox.Show(this, t.Exception.InnerException.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }));
            });
        }

        void ResetResInfo()
        {
            lbResLen.Text = "0";
            lbResType.Text = "";
            lbStatusCode.Text = "200";
            lbStatusText.Text = "";
            lbResDuration.Text = "0ms";
            tbResponse.Text = "";
        }

        async Task DoSend()
        {
            var contentTypes = new Dictionary<string, string>()
            {
                { "none", "text/plain" },
                { "json", "application/json" },
                { "formdata", "multipart/form-data" },
            };

            // 准备数据
            var method = cbMethod.Text.Trim();
            var url = tbUrl.Text.Trim();

            if (string.IsNullOrWhiteSpace(method))
            {
                throw new Exception("Method 不能为空");
            }
            if (string.IsNullOrWhiteSpace(url))
            {
                throw new Exception("URL 不能为空");
            }

            var contentType = tabParams.SelectedTab.Text;
            var headers = new Dictionary<string, string>();
            foreach (var header in requestHeader)
            {
                if (
                    //header.Send && 
                    string.IsNullOrWhiteSpace(header.Key))
                {
                    headers.Add(header.Key, header.Value);
                }
            }

            object body = null;
            if (contentType == "json")
            {
                body = Json.Deserialize(tbParamJson.Text);
            }
            else if (contentType == "none")
            {
                body = tbParamNone.Text;
            }
            else if (contentType == "formdata")
            {
                var form = new Dictionary<string, object>();
                foreach (var item in gridFormData.Rows)
                {
                    var row = item as DataGridViewRow;
                    var key = row.Cells[0].Value?.ToString();

                    if (string.IsNullOrWhiteSpace(key))
                    {
                        continue;
                    }

                    object value = row.Cells[1].Value?.ToString();
                    var isFile = row.Cells[2].Value != null && (bool)row.Cells[2].Value;

                    if (isFile && value != null)
                    {
                        value = new FileInfo(value.ToString());
                    }

                    form.Add(key, value);
                }
                body = form;
            }

            var result = await http.SendRequestAsync(url, new HttpMethod(method), body, contentTypes[contentType], headers);

            UpdateResponse(result);
        }

        void UpdateResponse(HttpResponseInfo result)
        {
            if (result == null)
            {
                return;
            }

            lbResLen.Text = FormatBytes(result.ContentLength);
            lbResType.Text = result.ContentType;
            lbStatusCode.Text = result.StatusCode.ToString();
            lbStatusText.Text = result.StatusText;
            lbResDuration.Text = result.Duration.ToString() + "ms";

            if (result.ContentType.Contains("json") || result.ContentType.Contains("text") || result.ContentType.Contains("xml"))
            {
                string text = null;
                try
                {
                    text = Encoding.UTF8.GetString(result.Body);
                }
                catch
                {
                }
                //object obj = null;
                //try
                //{
                //    Json.Deserialize(text);
                //    text = obj as string;
                //}
                //catch
                //{
                //}

                tbResponse.Text = text;
            }

            responseHeader.Clear();
            foreach (var header in result.Headers)
            {
                responseHeader.Add(new HeaderItem()
                {
                    Key = header.Key,
                    Value = header.Value
                });
            }
        }

        public static string FormatBytes(long bytes)
        {
            if (bytes < 0) throw new ArgumentOutOfRangeException(nameof(bytes), "Byte count cannot be negative.");

            string[] units = { "B", "KB", "MB", "GB", "TB" };
            double formattedSize = bytes;
            int unitIndex = 0;

            while (formattedSize >= 1024 && unitIndex < units.Length - 1)
            {
                formattedSize /= 1024;
                unitIndex++;
            }

            return $"{formattedSize:0.##} {units[unitIndex]}"; // 保留两位小数  
        }

        private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex != 3)
            {
                return;
            }
            var row = e.RowIndex;

            var isFile = gridFormData.Rows[row].Cells[2].Value;
            if (isFile == null || !(bool)isFile)
            {
                return;
            }

            if (openFileDialog1.ShowDialog(this) != DialogResult.OK)
            {
                return;
            }
            gridFormData.Rows[row].Cells[1].Value = openFileDialog1.FileName;
        }
    }
}
